﻿using Abp.Application.Services.Dto;
using Abp.Collections.Extensions;
using Abp.Domain.Repositories;
using Abp.Linq.Extensions;
using Abp.Organizations;
using Camc.Quality.Bop;
using Camc.Quality.Common.CommonDate;
using Camc.Quality.DataCenter.ProductTaskBoard;
using Camc.Quality.DataDictionary;
using Camc.Quality.ProductionControl;
using Camc.Quality.ProductionPlan;
using Camc.Quality.Quality;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Camc.Quality.DataCenter
{
    public class ProductTaskBoardAppService : QualityAppServiceBase
    {
        private readonly IRepository<ProductionScheduler, Guid> _productionSchedulerRepository;
        private readonly IRepository<OrganizationUnit, long> _organizationUnitRepository;
        private readonly IRepository<Sys_Code, Guid> _sysCodeRepository;
        private readonly IRepository<BopDesc, Guid> _bopDescRepository;
        private readonly IRepository<WorkStepEntity, Guid> _workStepEntityRepository;
        private readonly IRepository<TechniqueEntity, Guid> _techniqueEntityRepository;
        private readonly IRepository<BopNode, Guid> _bopNodeRepository;
        private readonly IRepository<ProcessesEntity, Guid> _processesEntityRepository;
        public ProductTaskBoardAppService(IRepository<ProductionScheduler, Guid> productionSchedulerRepository,
                                          IRepository<OrganizationUnit, long> organizationUnitRepository,
                                          IRepository<Sys_Code, Guid> sysCodeRepository,
                                          IRepository<BopDesc, Guid> bopDescRepository,
                                          IRepository<WorkStepEntity, Guid> workStepEntityRepository,
                                          IRepository<TechniqueEntity, Guid> techniqueEntityRepository,
                                          IRepository<BopNode, Guid> bopNodeRepository,
                                          IRepository<ProcessesEntity, Guid> processesEntityRepository
    )
        {
            _productionSchedulerRepository = productionSchedulerRepository;
            _organizationUnitRepository = organizationUnitRepository;
            _sysCodeRepository = sysCodeRepository;
            _bopDescRepository = bopDescRepository;
            _workStepEntityRepository = workStepEntityRepository;
            _techniqueEntityRepository = techniqueEntityRepository;
            _bopNodeRepository = bopNodeRepository;
            _processesEntityRepository = processesEntityRepository;
        }
        /// <summary>
        /// 车间生产看板报表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public PagedResultDto<ProductionReportOutput> GetTaskReportList(GetTaskReportListInput input)
        {
            //所有工步任务
            var workStepList = from bopdesc in _bopDescRepository.GetAll()
                                .WhereIf(input.ModelId != Guid.Empty && input.ModelId != null, d => d.ModelId == input.ModelId)
                                .WhereIf(input.LotNoId != Guid.Empty && input.LotNoId != null, d => d.LotNoId == input.LotNoId)
                                join bopnode in _bopNodeRepository.GetAll()
                                on bopdesc.Id equals bopnode.BopDescId
                                join tech in _techniqueEntityRepository.GetAll()
                                on bopnode.TechniqueEntityId equals tech.Id
                                join ws in _workStepEntityRepository.GetAll()
                                on tech.Id equals ws.TechniqueEntityId
                                join pe in _processesEntityRepository.GetAll()
                                on ws.ProcessesEntityId equals pe.Id
                                select new ProductionScheduler
                                {
                                    NodeId = ws.Id,
                                    Model = bopdesc.Model,
                                    ModelId = bopdesc.ModelId,
                                    LotNo = bopdesc.LotNo,
                                    LotNoId = bopdesc.LotNoId,
                                    TechniqueName = tech.TechniqueName,
                                    TechniqueNumber = tech.TechniqueNumber,
                                    DrawingNo = "工序" + pe.ProcessesSequence,
                                    ProductionName = pe.ProcessesName,
                                    WorkStepDrawingNo = "工步" + pe.ProcessesSequence + "-" + ws.WorkStepNumber.ToString(),
                                    WorkStepName = ws.WorkStepName,
                                    WorkingHour = ws.WorkStepWorking,
                                    CreationTime = ws.CreationTime
                                };
            if (workStepList.Count() > 0)
            {
                //未安排生产计划的工步任务
                var notArrangementIdList = workStepList.Select(d=>d.NodeId).Except(_productionSchedulerRepository.GetAll().Select(s=>s.NodeId));
                var notArrangementList = from ws in workStepList
                                         join na in notArrangementIdList
                                         on ws.NodeId equals na
                                         select ws;

                //已安排生产计划的工步任务
                var productionSchedulerList = (from ws in workStepList
                                               join ps in _productionSchedulerRepository.GetAll()
                                               on ws.NodeId equals ps.NodeId
                                               select ps).ToList();
                if ((input.StartDateTime != null || input.EndDateTime != null) || input.OrganizationUnitId != null)
                {
                    //开始结束日期和班组人员筛选
                    productionSchedulerList = productionSchedulerList.WhereIf(input.StartDateTime != null, d => d.StartTime >= input.StartDateTime)
                        .WhereIf(input.EndDateTime != null, d => d.EndTime <= input.EndDateTime)
                        .WhereIf(input.OrganizationUnitId != null, d => d.OrganizationUnitId != null && d.OrganizationUnitId.Contains(input.OrganizationUnitId.ToString())).ToList();
                    //未安排生产计划的工步任务没有开始完成时间和班组人员，所以不计算这部分
                    notArrangementList = null;
                }
                List<ProductionScheduler> productionReportOutput = new List<ProductionScheduler>();
                productionReportOutput.AddRange(productionSchedulerList);
                List<ProductionScheduler> completeList = new List<ProductionScheduler>();
                List<ProductionScheduler> productingList = new List<ProductionScheduler>();
                List<ProductionScheduler> yanqiList = new List<ProductionScheduler>();
                List<ProductionScheduler> noMatchList = new List<ProductionScheduler>();
                List<ProductionScheduler> matchedList = new List<ProductionScheduler>();
                //已完成
                completeList = productionSchedulerList.Where(s => s.ProductingStatus == ProductingStatus.已完成).ToList();
                if (completeList.Count > 0)
                {
                    productionSchedulerList.RemoveAll(d => completeList.FindIndex(s => s.Id == d.Id) != -1);
                }
                //生产中
                var productTemp = productionSchedulerList.Where(s => s.ProductingStatus == ProductingStatus.生产中).ToList();
                if (productTemp.Count > 0)
                {
                    productionSchedulerList.RemoveAll(d => productTemp.FindIndex(s => s.Id == d.Id) != -1);
                }
                var proC = productTemp.Where(d => d.EndTime != null);
                //延期
                yanqiList = proC.Where(d => DateTime.Compare(DateTime.Now, d.EndTime.Value) < 0).ToList();
                if (yanqiList.Count > 0)
                {
                    productTemp.RemoveAll(d => yanqiList.FindIndex(s => s.Id == d.Id) != -1);
                }
                productingList = productTemp;
                //已排配
                matchedList = productionSchedulerList.Where(d => d.StartTime != null || d.EndTime != null).ToList();
                //未排配
                noMatchList = productionSchedulerList.Except(matchedList).ToList();
                //全部查询
                if (input.ProductingStatus == 0 || input.ProductingStatus == null)
                {
                    if (notArrangementList != null)
                    {
                        productionReportOutput.AddRange(notArrangementList);
                    }
                }
                //已排配查询
                if (input.ProductingStatus == 1) productionReportOutput = matchedList;
                //已完成查询
                if (input.ProductingStatus == 2) productionReportOutput = completeList;
                //未排配查询
                if (input.ProductingStatus == 4)
                {
                        if (notArrangementIdList.Count() > 0)
                        {
                            productionReportOutput = noMatchList.Union(notArrangementList).ToList();
                        }
                        productionReportOutput = noMatchList;
                }
                //生产中查询
                if (input.ProductingStatus == 3) productionReportOutput = productingList;
                //已延迟查询
                if (input.ProductingStatus == 7) productionReportOutput = yanqiList;
                var temp = ObjectMapper.Map<List<ProductionReportOutput>>(productionReportOutput.OrderByDescending(s=>s.CreationTime));
                var count = temp.Count();
                return new PagedResultDto<ProductionReportOutput>(count, temp);
            }
            else
            {
                return new PagedResultDto<ProductionReportOutput>();
            }
        }
        /// <summary>
        /// 车间生产看板数字统计
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public TaskReportTitleDto GetTaskReportTitle(GetTaskReportTitleInput input)
        {
            //所有工步任务
            var workStepList = (from bopdesc in _bopDescRepository.GetAll()
                                .WhereIf(input.ModelId != Guid.Empty && input.ModelId != null, d => d.ModelId == input.ModelId)
                                 .WhereIf(input.LotNoId != Guid.Empty && input.LotNoId != null, d => d.LotNoId == input.LotNoId)
                                join bopnode in _bopNodeRepository.GetAll()
                               on bopdesc.Id equals bopnode.BopDescId
                                join tech in _techniqueEntityRepository.GetAll()
                                on bopnode.TechniqueEntityId equals tech.Id
                                join ws in _workStepEntityRepository.GetAll()
                                on tech.Id equals ws.TechniqueEntityId
                                select new
                                {
                                    Id = ws.Id
                                });
            TaskReportTitleDto taskReportTitleDto = new TaskReportTitleDto();
            if (workStepList.Count() > 0)
            {
                //未安排生产计划的工步任务
                var count = workStepList.Except(from ps in _productionSchedulerRepository.GetAll() select new { Id = ps.NodeId }).Count();
                //已安排生产计划的工步任务
                var productionSchedulerList = (from ws in workStepList
                                               join ps in _productionSchedulerRepository.GetAll()
                                               on ws.Id equals ps.NodeId
                                               select ps).ToList();
                if ((input.StartDateTime == null && input.EndDateTime == null) && input.OrganizationUnitId == null)
                {
                    //任务总数
                    taskReportTitleDto.Total = workStepList.Count();
                }
                else
                {
                    //开始结束日期和班组人员筛选
                    productionSchedulerList = productionSchedulerList.WhereIf(input.StartDateTime != null, d => d.StartTime >= input.StartDateTime)
                        .WhereIf(input.EndDateTime != null, d => d.EndTime <= input.EndDateTime)
                        .WhereIf(input.OrganizationUnitId != null, d => d.OrganizationUnitId != null && d.OrganizationUnitId.Contains(input.OrganizationUnitId.ToString())).ToList();

                    //任务总数
                    taskReportTitleDto.Total = productionSchedulerList.Count();
                    //未安排生产计划的工步任务没有开始完成时间和班组人员，所以不计算这部分
                    count = 0;
                }
                List<ProductionScheduler> completeList = new List<ProductionScheduler>();
                List<ProductionScheduler> productingList = new List<ProductionScheduler>();
                List<ProductionScheduler> yanqiList = new List<ProductionScheduler>();
                List<ProductionScheduler> noMatchList = new List<ProductionScheduler>();
                List<ProductionScheduler> matchedList = new List<ProductionScheduler>();
                //已完成
                completeList = productionSchedulerList.Where(s => s.ProductingStatus == ProductingStatus.已完成).ToList();
                if (completeList.Count > 0)
                {
                    productionSchedulerList.RemoveAll(d => completeList.FindIndex(s => s.Id == d.Id) != -1);
                }
                //生产中
                var productTemp = productionSchedulerList.Where(s => s.ProductingStatus == ProductingStatus.生产中).ToList();
                if (productTemp.Count > 0)
                {
                    productionSchedulerList.RemoveAll(d => productTemp.FindIndex(s => s.Id == d.Id) != -1);
                }
                var proC = productTemp.Where(d => d.EndTime != null);
                //延期
                yanqiList = proC.Where(d => DateTime.Compare(DateTime.Now, d.EndTime.Value) < 0).ToList();
                if (yanqiList.Count > 0)
                {
                    productTemp.RemoveAll(d => yanqiList.FindIndex(s => s.Id == d.Id) != -1);
                }
                productingList = productTemp;
                //已排配
                matchedList = productionSchedulerList.Where(d => d.StartTime != null || d.EndTime != null).ToList();
                //未排配
                noMatchList = productionSchedulerList.Except(matchedList).ToList();
                //已排配数量=未排配+未安排生产计划的工步任务
                taskReportTitleDto.Arrangement = matchedList.Count();
                //未排配数量
                taskReportTitleDto.NotArrangement = noMatchList.Count() + count;
                //已完成数量
                taskReportTitleDto.Complete = completeList.Count();
                //生产中数量
                taskReportTitleDto.InProduction = productingList.Count();
                //已延期数量
                taskReportTitleDto.Delay = yanqiList.Count();
                return taskReportTitleDto;
            }
            else
            {
                return new TaskReportTitleDto();
            }
        }
        /// <summary>
        /// 班组下拉列表
        /// </summary>
        /// <returns></returns>
        public List<LabelCollectString> GetOrganizationUnitForBoard()
        {
            var query = from ou in _organizationUnitRepository.GetAll()
                        select new LabelCollectString
                        {
                            Label = ou.DisplayName,
                            Value = ou.Id.ToString()
                        };
            if (query.Count() > 0)
            {
                return query.ToList();
            }
            return new List<LabelCollectString>();
        }
    }
}
